///////////////////////////////////////////////////////////
//  Page.cpp
//  Implementation of the Class Page
//  Created on:      21-Aug-2013 11:05:05 PM
//  Original author: Jakkaphan Aiemcharoenjit
///////////////////////////////////////////////////////////

#include "Page.h"
#include "Choices.h"
#include "DataSchemaXML.h"
#include "IItem.h"
#include "IHeader.h"
#include <ctime>

using namespace Data;

Page::Page(IPage::PageType _type)
{
  this->m_type = IObject::PAGE_T;
  this->m_pageType = _type;
  this->m_name = _T("");
  this->m_templateName = _T("");
  this->m_title = _T("");
  this->m_comment = _T("");
  this->m_parent = NULL;
  this->m_buildTime = _T("");
  this->m_templateTime = _T("");

  if(_type == IPage::CHOICEPAGE_T)
    this->m_choices = new Choices();
  else
    this->m_choices = NULL;
}


Page::Page(const Page& anotherPage)
{
  this->m_type = IObject::PAGE_T;
  this->m_pageType = anotherPage.m_pageType;
  this->m_name = anotherPage.m_name;
  this->m_templateName = anotherPage.m_templateName;
  this->m_title = anotherPage.m_title;
  this->m_comment = anotherPage.m_comment;
  this->m_parent = anotherPage.m_parent;
  this->m_buildTime = anotherPage.m_buildTime;
  this->m_templateTime = anotherPage.m_templateTime;

  if(anotherPage.m_choices)
    this->m_choices = static_cast<IChoices*>(anotherPage.m_choices->Clone());
  else
    this->m_choices = NULL;

  int countChilds = anotherPage.CountChilds();
  for(int index = 0; index < countChilds; index++)
  {
    IObject* cloneData = anotherPage.GetChild(index)->Clone();
    this->m_childs.push_back(cloneData);
    switch(cloneData->GetType())
    {
    case IObject::ITEM_T:
      {
        dynamic_cast<IItem*>(cloneData)->SetParent(this);
      }
      break;
    case IObject::HEARDER_T:
      {
        dynamic_cast<IHeader*>(cloneData)->SetParent(this);
      }
      break;
    default: break;
    }
  }
}


Page::~Page()
{
  if(this->m_choices)
    delete this->m_choices;

  std::vector<IObject*>::iterator childItem = this->m_childs.begin();
  while(childItem != this->m_childs.end())
  {
    delete (*childItem);
    (*childItem) = NULL;
    childItem++;
  }

  this->m_childs.clear();
  this->m_choices = NULL;
  this->m_parent = NULL;
}


IObject::ObjectType Page::GetType() const 
{
	return  this->m_type;
}


IPage::PageType Page::GetPageType() const 
{

	return  this->m_pageType;
}


String_t Page::GetName() const 
{

	return  this->m_name;
}


IObject* Page::GetChild(unsigned int index) const 
{

	return  this->m_childs[index];
}


String_t Page::GetTemplateName() const 
{

	return  this->m_templateName;
}


String_t Page::GetTitle() const 
{

	return  this->m_title;
}


IChoices* Page::GetChoices() const 
{

	return  this->m_choices;
}


String_t Page::GetComment() const 
{

	return  this->m_comment;
}


void Page::AppendChild(IObject* item)
{
  switch(item->GetType())
  {
  case IObject::HEARDER_T:
    {
      IHeader* childHeader = dynamic_cast<IHeader*>(item);
      childHeader->SetParent(this);
    }
    break;
  case IObject::ITEM_T:
    {
      IItem* itemData = dynamic_cast<IItem*>(item);
      itemData->SetParent(this);
    }
    break;
  default: break;
  }
  this->m_childs.push_back(item);
}


void Page::InsertChild(unsigned int index, IObject* item)
{
  switch(item->GetType())
  {
  case IObject::HEARDER_T:
    {
      IHeader* childHeader = dynamic_cast<IHeader*>(item);
      childHeader->SetParent(this);
    }
    break;
  case IObject::ITEM_T:
    {
      IItem* itemData = dynamic_cast<IItem*>(item);
      itemData->SetParent(this);
    }
    break;
  default: break;
  }
  this->m_childs.insert(this->m_childs.begin() + index, item);
}


IObject* Page::RemoveChild(unsigned int index)
{
	return  *(this->m_childs.erase(this->m_childs.begin() + index));;
}


int Page::CountChilds() const 
{

	return (int)this->m_childs.size();
}


void Page::SetName(const String_t& name)
{
  this->m_name = name;
}


void Page::SetTemplateName(const String_t& name)
{
  this->m_templateName = name;
}


void Page::SetTitle(const String_t& title)
{
  this->m_title = title;
}


void Page::SetComment(const String_t& comment)
{
  this->m_comment = comment;
}


void Page::SetPageType(IPage::PageType pageType)
{
  this->m_pageType = pageType;
}


IObject* Page::Clone()
{
  IPage* clonePage = new Page(*this);
	return  clonePage;
}


String_t Page::ToXML()
{
  //<Page name="Template1" templatename="Template1" pagetype="choice">
  //  <Choices>
  //    <Choice index="0">Yes</Choice>
  //    <Choice index="1">No</Choice>
  //    <Choice index="2">Cancel</Choice>
  //  </Choices>
  //  <Title>This is an example title of page.</Title>
  //  <Comment>This is an example comment!</Comment>
  //  <CollectionItems>
  //    <Header name="Header1">
  //      <Item name="Item1">
  //        <Comment>This is an example comment!</Comment>
  //        <UseInteger>0</UseInteger>
  //      </Item>
  //      <Item name="Item2">
  //        <Comment>This is an example comment!</Comment>
  //        <UseInteger>1</UseInteger>
  //      </Item>
  //    </Header>
  //  </CollectionItems>
  //</Page>

  String_t xml = _T("<") + DataSchemaXML::PAGE_ELEMENT;
  String_t context = this->m_name;
  replaceTextXML(context);
  if(!this->m_name.empty())
    xml += _T(" ") + DataSchemaXML::NAME_ATTR + _T("=\"") + context + _T("\"");

  context = this->m_templateName;
  replaceTextXML(context);
  if(!this->m_templateName.empty())
    xml += _T(" ") + DataSchemaXML::TEMPLATENAME_ATTR + _T("=\"") + context + _T("\"");

  // Add new attribute for date time (8 Nov 2013)
  if(!this->m_templateTime.empty())
    xml += _T(" ") + DataSchemaXML::TEMPLATETIME_ATTR + _T("=\"") + this->m_templateTime + _T("\"");

  if(!this->m_buildTime.empty())
    xml += _T(" ") + DataSchemaXML::BUILDTIME_ATTR + _T("=\"") + this->m_buildTime + _T("\"");

  xml += _T(" ") + DataSchemaXML::PAGETYPE_ATTR + _T("=\"") + PageTypeDesc() + _T("\">");
  
  if(this->m_choices)
    xml += m_choices->ToXML();

  context = this->m_title;
  replaceTextXML(context);
  if(!this->m_title.empty())
    xml += _T("<") + DataSchemaXML::TITLEPAGE_ELEMENT + _T(">") + context + _T("</") + DataSchemaXML::TITLEPAGE_ELEMENT + _T(">");

  context = this->m_comment;
  replaceTextXML(context);
  if(!this->m_comment.empty())
    xml += _T("<") + DataSchemaXML::COMMENT_ELEMENT + _T(">") + context + _T("</") + DataSchemaXML::COMMENT_ELEMENT + _T(">");

  xml += _T("<") + DataSchemaXML::COLLECTIONITEM_ELEMENT + _T(">");
  std::vector<IObject*>::iterator childItem = this->m_childs.begin();

  while(childItem != this->m_childs.end())
  {
    xml += (*childItem)->ToXML();
    childItem++;
  }

    
  xml += _T("</") + DataSchemaXML::COLLECTIONITEM_ELEMENT + _T(">");
  xml += _T("</") + DataSchemaXML::PAGE_ELEMENT + _T(">"); 

	return  xml;
}

IObject* Page::operator[]( unsigned int index )
{
  return this->m_childs[index];
}

String_t Data::Page::PageTypeDesc()
{
  switch(this->m_pageType)
  {
  case IPage::TEXTPAGE_T:
    return _T("text");
  case IPage::CHOICEPAGE_T :
    return _T("choice");
  case IPage::CHECKPAGE_T:
    return _T("check");
  default: return _T("");
  }
}

void Data::Page::SetChoices( IChoices* choices )
{
  if(this->m_choices)
    delete this->m_choices;

  this->m_choices = choices;
  this->m_pageType = IPage::CHOICEPAGE_T;
}

void Data::Page::SetPageType( const String_t& pageType )
{
  if(pageType == _T("text"))
    this->m_pageType = IPage::TEXTPAGE_T;
  else if(pageType == _T("choice"))
    this->m_pageType = IPage::CHOICEPAGE_T;
  else if(pageType == _T("check"))
    this->m_pageType = IPage::CHECKPAGE_T;
}

void Data::Page::UpdateTemplateTime()
{
	// current date/time based on current system
	time_t dateNow = time(0);
	StringStream_t strStream;
	tm *pltm = localtime(&dateNow);
	strStream << pltm->tm_mday << _T("/") << 1 + pltm->tm_mon << _T("/") << 1990 + pltm->tm_year;
	strStream << _T(" ") << pltm->tm_hour << _T(":") << pltm->tm_min;
	this->m_templateTime = strStream.str().c_str();
}

void Data::Page::UpdateBuildTime()
{
	// current date/time based on current system
	time_t dateNow = time(0);
	StringStream_t strStream;
	tm *pltm = localtime(&dateNow);
	strStream << pltm->tm_mday << _T("/") << 1 + pltm->tm_mon << _T("/") << 1990 + pltm->tm_year;
	strStream << _T(" ") << pltm->tm_hour << _T(":") << pltm->tm_min;
	this->m_buildTime = strStream.str().c_str();
}

String_t Data::Page::GetTemplateTime() const
{
  return this->m_templateTime;
}

String_t Data::Page::GetBuildTime() const
{
  return this->m_buildTime;
}

void Data::Page::SetTemplateTime( String_t datetime )
{
  this->m_templateTime = datetime;
}

void Data::Page::SetBuildTime( String_t datetime )
{
  this->m_buildTime = datetime;
}

void Page::ClearItems()
{
  if(this->m_choices)
    delete this->m_choices;

  std::vector<IObject*>::iterator childItem = this->m_childs.begin();
  while(childItem != this->m_childs.end())
  {
    delete (*childItem);
    (*childItem) = NULL;
    childItem++;
  }

  this->m_childs.clear();
  this->m_choices = NULL;
  this->m_parent = NULL;
}

void Page::CopyPage( IPage* tempPage )
{
  this->m_buildTime = tempPage->GetBuildTime();
	this->m_templateTime = tempPage->GetTemplateTime();
	this->m_comment = tempPage->GetComment();
	this->m_title = tempPage->GetTitle();
	this->m_name = tempPage->GetName();
	this->m_templateName = tempPage->GetTemplateName();

	this->m_choices = dynamic_cast<IChoices*>(tempPage->GetChoices()->Clone());
  int childs = tempPage->CountChilds();
  for(int index = 0; index < childs; index++)
  {
    this->m_childs.push_back(tempPage->GetChild(index)->Clone());
  }
  this->m_parent = tempPage->GetParent();
}

IObject* Page::GetParent()
{
	return this->m_parent;
}


void Page::SetParent(IObject* parent)
{
  this->m_parent = parent;
}